#include "RootSystem.h"
RootSystem::RootSystem() :
	m_isEnd(false),
	m_rootDirectory("G:\\Programming Projects\\Game Engine Practice\\")
{

}
RootSystem::~RootSystem()
{

}
void RootSystem::InitializeWindows(int& screenWidth, int& screenHeight,bool _fullScreen)
{
	WNDCLASSEX wc;
	DEVMODE dmScreenSettings;
	int posX, posY;
	ApplicationHandle = this;
	hinstance = GetModuleHandle(NULL);
	applicationName = "Game Engine Practice";
	wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
	wc.lpfnWndProc = WndProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hinstance;
	wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
	wc.hIconSm = wc.hIcon;
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wc.lpszMenuName = NULL;
	wc.lpszClassName = applicationName;
	wc.cbSize = sizeof(WNDCLASSEX);
	
	RegisterClassEx(&wc);
	screenWidth = GetSystemMetrics(SM_CXSCREEN);
	screenHeight = GetSystemMetrics(SM_CYSCREEN);

	if (_fullScreen)
	{
		memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
		dmScreenSettings.dmSize = sizeof(dmScreenSettings);
		dmScreenSettings.dmPelsWidth = (unsigned long)screenWidth;
		dmScreenSettings.dmPelsHeight = (unsigned long)screenHeight;
		dmScreenSettings.dmBitsPerPel = 32;
		dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
		ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);
		posX = 0;
		posY = 0;
	}
	else
	{
		screenWidth = 800;
		screenHeight = 600;
		posX = (GetSystemMetrics(SM_CXSCREEN) - screenWidth) / 2;
		posY = (GetSystemMetrics(SM_CYSCREEN) - screenHeight) / 2;
	}

	if (_fullScreen)
	{
		hwnd = CreateWindowEx(WS_EX_APPWINDOW, applicationName, applicationName, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_POPUP, posX, posY, screenWidth, screenHeight, NULL, NULL, hinstance, NULL);
	}
	else
	{
		hwnd = CreateWindowEx(WS_EX_APPWINDOW, applicationName, applicationName, WS_OVERLAPPEDWINDOW, posX, posY, screenWidth, screenHeight, NULL, NULL, hinstance, NULL);
	}
	ShowWindow(hwnd, SW_SHOW);
	SetForegroundWindow(hwnd);
	SetFocus(hwnd);
}
void RootSystem::Initialize()
{
	int screenWidth = 0;
	int screenHeight = 0;
	InitializeWindows(screenWidth, screenHeight, false);
	camera = new Camera(std::vector<float>{-5.0, 0.0, 0.0}, "camera");
	rendering = new Rendering;
	rendering->Initialize(screenWidth, screenHeight, hwnd, false, false, false, 1000.0f, 0.1f, camera);
	frameTimer = new FrameTimer();
	input = new Input();
}
void RootSystem::Shutdown()
{
	delete frameTimer;
	frameTimer = NULL;

	rendering->Shutdown();
	delete rendering;
	rendering = NULL;
}
void RootSystem::Update()
{
	frameTimer->Update();
	double frameTime = frameTimer->GetPredictedFrameTime();
	/*
	for (int i = 0;i < gameObjects.size();++i)
	{
		gameObjects[i]->Render(rendering->GetRenderingModels());
	}
	*/
	rendering->Update(gameObjects,m_directionalLights,m_pointLights,m_spotLights);
}
void RootSystem::AddGameObject(GameObject* newGameObject)
{
	gameObjects.push_back(newGameObject);
}
void RootSystem::AddDirectionalLight(DirectionalLight* directionalLight)
{
	m_directionalLights.push_back(directionalLight);
}
void RootSystem::AddPointLight(PointLight* pointLight)
{
	m_pointLights.push_back(pointLight);
}
void RootSystem::AddSpotLight(SpotLight* spotLight)
{
	m_spotLights.push_back(spotLight);
}
void RootSystem::Run()
{
	MSG systemMessage;
	ZeroMemory(&systemMessage, sizeof(systemMessage));
	while (!m_isEnd)
	{
		if (PeekMessage(&systemMessage, NULL, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&systemMessage);
			DispatchMessage(&systemMessage);
		}
		if (systemMessage.message == WM_QUIT)
		{
			m_isEnd = true;
		}
		Update();
	}
}
LRESULT CALLBACK RootSystem::MessageHandler(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam)
{
	switch (umessage)
	{
	case WM_KEYDOWN:
		input->KeyDown((unsigned int)wparam);
		return 0;
	case WM_KEYUP:
		input->KeyUp((unsigned int)wparam);
		return 0;
	case WM_MOUSEMOVE:
		{
			double x = LOWORD(lparam);
			double y = HIWORD(lparam);
			input->MouseMove(x, y);
		}
		return 0;
	case WM_LBUTTONDOWN:
	case WM_LBUTTONUP:
	case WM_MBUTTONDOWN:
	case WM_MBUTTONUP:
	case WM_RBUTTONDOWN:
	case WM_RBUTTONUP:
		input->MouseOperate(umessage);
		return 0;
	default:
		return DefWindowProc(hwnd, umessage, wparam, lparam);
	}
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT umessage, WPARAM wparam, LPARAM lparam)
{
	switch (umessage)
	{
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	case WM_CLOSE:
		PostQuitMessage(0);
		return 0;
	default:
		return  ApplicationHandle->MessageHandler(hwnd, umessage, wparam, lparam);
	}
}